import SVGGraphics from "../class/SVGGraphics";

export const square = (v) => v * v;// 平方
export const pt2px = (pt) => pt * ((window.devicePixelRatio) || 1);//px 转 pt

// export const renderer = window["R"] = new PIXI.lights.WebGLDeferredRenderer(document.body.clientWidth - 2 || 400, document.body.clientHeight - 2 || 300);
export const renderer = window["R"] = PIXI.autoDetectRenderer(document.body.clientWidth - 2 || 400, document.body.clientHeight - 2 || 300);
document.body.appendChild(renderer.view);
export const VIEW_WIDTH = renderer.view.width;
export const VIEW_HEIGHT = renderer.view.height;
export const VIEW_CENTER = new PIXI.Point(renderer.view.width / 2, renderer.view.height / 2);
export const L_ANI_TIME = 1225;
export const B_ANI_TIME = 375;
export const M_ANI_TIME = 225;
export const S_ANI_TIME = 195;
export const on = (obj: PIXI.EventEmitter, eventName: string, handle) => {
    return eventName.split("|").map(en => {
        if (en === "touchenter") {
            return obj.on("touchmove", (e) => {
                console.log(e.target === obj);
                if (e.target === this) {
                    handle(e);
                }
            });
        } else if (en === "touchout") {
            // return obj.on("touchmove", (e) => {
            //     console.log(e.target === this);
            //     if (e.target === this) {
            //         handle(e);
            //     }
            // });
        } else {
            return obj.on(en, handle)
        }
    })
}
interface Point {
    x: number,
    y: number
}
export function getLineSamePath(line_A: Point[], line_B: Point[]) {
    var line_index = -1;
    var line_len = 0;
    var max_line_index = -1;
    var max_line_len = 0;
    for (var i = 0, point_a, len_a = line_A.length; point_a = line_A[i]; i += 1) {
        for (var j = 0, point_b; point_b = line_B[j]; j += 1) {
            if (point_a.x === point_b.x && point_a.y === point_b.y) {
                line_index = i;
                line_len = 1;
                for (var _j = j + 1, _i = i + 1, _point_a, _point_b; (_point_a = line_A[_i]) && (_point_b = line_B[_j]); _i += 1, _j += 1) {
                    if (_point_a.x === _point_b.x && _point_a.y === _point_b.y) {
                        line_len += 1;
                    }
                }
                if (max_line_len < line_len && line_len > 1) {
                    max_line_len = line_len;
                    max_line_index = line_index;
                    // break
                    return {
                        line_A_index: i,
                        line_B_index: j,
                        line_len: max_line_len
                    };
                }
            }
        }
    }
    return null;
}
export function BaseLineAnimate(start_line: Point[], end_line: Point[], progress: number) {
    var i, start_point, end_point, res_point, res_line;
    var s_len = start_line.length;
    var e_len = end_line.length;
    if (s_len > e_len) { //多点变少点，进行点合并
        var r_len = e_len + (s_len - e_len) * (1 - progress);
        res_line = Array(Math.round(r_len));
        /**合并指数，点数不同，进行合并*/
        var v = res_line.length / s_len;
        /**累计的V值*/
        var acc_v = 0;

        /**平均多少个开始点对应一个结束点*/
        var k = e_len / s_len;
        /**累计的K值*/
        var acc_k = 0;
		/**对应的结束点的下标
		 * k值始终是小于1的，所以这第一个值，肯定是0
		 */
        var e_i = 0;
        var r_i = 0;
        //一次性累计合并了几个点
        var acc_r;
        for (i = 0; start_point = start_line[i]; i += 1) {
            end_point = end_line[e_i];
            if (!end_point) {
                debugger
            }
            res_point = res_line[r_i];
            var res_point_x = (end_point.x - start_point.x) * progress + start_point.x
            var res_point_y = (end_point.y - start_point.y) * progress + start_point.y
            if (res_point) { //合并点
                var acc_r_bak = acc_r;
                acc_r += 1;
                res_point = {
                    x: (res_point.x * acc_r_bak + res_point_x) / acc_r,
                    y: (res_point.y * acc_r_bak + res_point_y) / acc_r,
                }
            } else {
                acc_r = 1;
                res_point = {
                    x: res_point_x,
                    y: res_point_y,
                }
            }
            res_line[r_i] = res_point;

            acc_k += k;
            e_i = Math.floor(acc_k); //acc_k始终小于e_len，所以使用floor正好对应下标
            acc_v += v;
            r_i = Math.floor(acc_v);
        }
    } else if (s_len < e_len) { //少点变多点，补点
        res_line = BaseLineAnimate(end_line, start_line, 1 - progress);
    } else { //点数相同
        res_line = Array(s_len);
        for (i = 0; start_point = start_line[i]; i += 1) {
            end_point = end_line[i];
            res_line[i] = {
                x: (end_point.x - start_point.x) * progress + start_point.x,
                y: (end_point.y - start_point.y) * progress + start_point.y,
            }
        }
    }
    return res_line;
}
export function LineAnimate(start_line: Point[], end_line: Point[], progress: number) {
    try {

        var same_line = getLineSamePath(start_line, end_line);
        if (same_line) {
            var mid_line = start_line.slice(same_line.line_A_index, same_line.line_A_index + same_line.line_len);

            var s_start_line = start_line.slice(0, same_line.line_A_index)
            var s_end_line = end_line.slice(0, same_line.line_B_index)
            if (s_end_line.length === 0 || s_start_line.length === 0) {
                var fix_point = mid_line.shift();
                s_start_line.push(fix_point)
                s_end_line.push(fix_point)
            }
            var bef_line = BaseLineAnimate(s_start_line, s_end_line, progress);

            var e_start_line = start_line.slice(same_line.line_A_index + same_line.line_len)
            var e_end_line = end_line.slice(same_line.line_B_index + same_line.line_len)
            if (e_start_line.length === 0 || e_end_line.length === 0) {
                var fix_point = mid_line.pop();
                e_start_line.unshift(fix_point)
                e_end_line.unshift(fix_point)
            }
            var aft_line = BaseLineAnimate(e_start_line, e_end_line, progress);
            return bef_line.concat(mid_line).concat(aft_line);
        } else {
            return BaseLineAnimate(start_line, end_line, progress);
        }
    } catch (e) {
        debugger
    }
}


var _current_stage: PIXI.Container;
var _current_stage_index: number = 0;
var _stages: PIXI.Container[] = [];
var _bg_color = null;
var _main_stage = new PIXI.Container();
var _bg: PIXI.Graphics;
export const stageManager = {
    get backgroundColor() {
        return _bg_color
    },
    set backgroundColor(new_color) {
        if (_bg_color !== new_color) {
            _bg_color = new_color
            // var new_bg = SVGGraphics.importFromSVG(`<circle cx="${VIEW_WIDTH / 2}" y="${VIEW_HEIGHT / 2}" r="100" fill="${_bg_color}"/>`)._graphics;
            var new_bg = SVGGraphics.importFromSVG(`<rect x="0" y="0" width="${VIEW_WIDTH}" height="${VIEW_HEIGHT}" fill="${_bg_color}"/>`)._graphics;

            _bg && _main_stage.removeChild(_bg);
            // _main_stage.addChildAt(_bg = new_bg, 0);
        }
    },
    set(stage: PIXI.Container) {
        if ((_current_stage_index = _stages.indexOf(stage)) === -1) {
            _current_stage_index = _stages.push(stage) - 1;
        }
        _current_stage = _stages[_current_stage_index];
        _main_stage.children[1] && _main_stage.removeChildAt(1);
        _main_stage.addChild(_current_stage);
        return stageManager;
    },
    get() {
        if (!_current_stage["__is_inited"]) {
            _current_stage["__is_inited"] = true;
            _current_stage.emit("init");
        }
        return _main_stage;
    },
    add(...stages: PIXI.Container[]) {
        _stages = _stages.concat(stages);
        return stageManager;
    },
    next() {
        if (_current_stage_index > _stages.length - 1) {
            return
        }
        _current_stage_index += 1;
        _current_stage = _stages[_current_stage_index];
        _main_stage.children[1] && _main_stage.removeChildAt(1);
        _main_stage.addChild(_current_stage);
        return _main_stage;
    }
};
stageManager.backgroundColor = "#999";
console.log(_main_stage)

const STATIC_MAP_SIZE = 620;
export var MAP_WIDTH = VIEW_WIDTH;
export var MAP_HEIGHT = VIEW_HEIGHT;
export var MAX_MAP_WIDTH = VIEW_WIDTH;
export var MAX_MAP_HEIGHT = VIEW_HEIGHT;
if (Math.max(VIEW_WIDTH, VIEW_HEIGHT) > STATIC_MAP_SIZE) {//fill 模式
    const _WH_BILI = VIEW_WIDTH / VIEW_HEIGHT
    if (_WH_BILI > 1) {
        MAX_MAP_WIDTH = STATIC_MAP_SIZE
        MAX_MAP_HEIGHT = Math.round(STATIC_MAP_SIZE / _WH_BILI);
    } else {
        MAX_MAP_HEIGHT = STATIC_MAP_SIZE;
        MAX_MAP_WIDTH = Math.round(STATIC_MAP_SIZE * _WH_BILI);
    }
}
MAP_WIDTH = 500;
MAP_HEIGHT = 500;
export const cbrt = Math["cbrt"] || function (x) {
    var y = Math.pow(Math.abs(x), 1 / 3);
    return x < 0 ? -y : y;
};
interface OffsetPoint {
    x?: number,
    y?: number
}

export function TextureGenerator(renderer: PIXI.CanvasRenderer | PIXI.WebGLRenderer, parent: PIXI.Container, unit_tex: PIXI.Texture, view_width: number, view_height: number, offset_x?: OffsetPoint, offset_y?: OffsetPoint) {

    const unit_width = unit_tex.width
    const unit_height = unit_tex.height
    offset_x || (offset_x = { x: 0, y: 0 })
    offset_y || (offset_y = { x: 0, y: 0 })
    var offset_x_x = isFinite(offset_x.x) ? offset_x.x : 0;
    var offset_x_y = isFinite(offset_x.y) ? offset_x.y : 0;
    var offset_y_x = isFinite(offset_y.x) ? offset_y.x : 0;
    var offset_y_y = isFinite(offset_y.y) ? offset_y.y : 0;
    // 偏移量必须大于0，用来减去的
    offset_x_x = offset_x_x % unit_width
    if (offset_x_x < 0) {
        offset_x_x += unit_width
    }
    offset_y_x = offset_y_x % unit_width
    if (offset_y_x < 0) {
        offset_y_x += unit_width
    }
    offset_x_y = offset_x_y % unit_height
    if (offset_x_y < 0) {
        offset_x_y += unit_height
    }
    offset_y_y = offset_y_y % unit_height
    if (offset_y_y < 0) {
        offset_y_y += unit_height
    }

    var normalTextureGenerator = new PIXI.Container;
    var start_x = 0;
    var start_y = 0;
    // console.log(
    //     offset_x_x,
    //     offset_x_y,
    //     offset_y_x,
    //     offset_y_y,
    //     "|",
    //     unit_width,
    //     unit_height
    // );

    var last_tile_x = -unit_width;
    var last_tile_y = -unit_height;
    for (var h = 0, j = 0; last_tile_y + unit_height < view_height; h += unit_height, j += 1) {
        for (var w = 0, i = 0; last_tile_x + unit_width < view_width; w += unit_width, i += 1) {
            var tile = new PIXI.Sprite(unit_tex);
            last_tile_x = tile.x = start_x + w - offset_x_x * i
            last_tile_y = tile.y = start_y + h - offset_x_y * i
            // console.log(i, j, "|", tile.x, tile.y)
            normalTextureGenerator.addChild(tile)
        }
        last_tile_x = -unit_width;
        start_x -= offset_y_x
        start_y -= offset_y_y
    }
    var rect_x = -offset_y_x + j * offset_y_x;
    var rect_y = -offset_x_y + i * offset_x_y;

    normalTextureGenerator.cacheAsBitmap = true;

    parent.addChild(normalTextureGenerator);
    var full_tex = normalTextureGenerator.generateTexture(renderer);
    parent.removeChild(normalTextureGenerator);
    var res_tex = new PIXI.Texture(full_tex.baseTexture, new PIXI.Rectangle(rect_x, rect_y, view_width + rect_x, view_height + rect_y))
    // console.log(-rect_x, -rect_y, view_width - rect_x, view_height - rect_y)
    return res_tex
}


class TilePositionPoint extends PIXI.Point {
    private _x: number
    get x() {
        return this._x
    }
    set x(v) {
        var old_x = this._x;
        if (old_x !== v) {
            this._x = v
            this.onXChanged(old_x, v)
        }
    }
    onXChanged(old_value: number, new_value: number) { }
    private _y: number
    get y() {
        return this._y
    }
    set y(v) {
        var old_y = this._y;
        if (old_y !== v) {
            this._y = v
            this.onYChanged(old_y, v)
        }
    }
    onYChanged(old_value: number, new_value: number) { }
}
export class TilingSprite extends PIXI.Sprite {
    view_width: number
    view_height: number
    repeat_width: number
    repeat_height: number

    tile_offset_x: OffsetPoint
    tile_offset_y: OffsetPoint
    constructor(tex: PIXI.Texture, view_width: number, view_height: number, repeat_width?: number, repeat_height?: number, tile_offset_x?: OffsetPoint, tile_offset_y?: OffsetPoint) {
        super(TextureGenerator(renderer, stageManager.get(), tex,
            view_width + (view_width % (repeat_width || (repeat_width = tex.width))) + repeat_width,
            view_height + (view_height % (repeat_height || (repeat_height = tex.height))) + repeat_height,
            tile_offset_x, tile_offset_y));

        this.view_width = view_width;
        this.view_height = view_height;
        this.repeat_width = repeat_width;
        this.repeat_height = repeat_height;
        this.tile_offset_x = tile_offset_x;
        this.tile_offset_y = tile_offset_y;

        this._tilePosition.onXChanged = (old_value, new_value) => {
            var x = new_value % repeat_width;
            if (x > 0) {
                x -= repeat_width
            }
            this.x = x
        }
        this._tilePosition.onYChanged = (old_value, new_value) => {
            var y = new_value % repeat_height;
            if (y > 0) {
                y -= repeat_height
            }
            this.y = y
        }
        // this.mask = new PIXI.Rectangle(0, 0, view_width, view_height);
    }
    private _tilePosition = new TilePositionPoint()
    get tilePosition() {
        return this._tilePosition
    }
    set tilePosition(p: PIXI.Point) {
        this._tilePosition.set(p.x, p.y)
    }
};

/** 获取线段交点 */
export function segmentsIntr(a: PIXI.Point, b: PIXI.Point, c: PIXI.Point, d: PIXI.Point) {  // 获取两条线的交点

    //线段ab的法线N1  
    var nx1 = (b.y - a.y), ny1 = (a.x - b.x);

    //线段cd的法线N2  
    var nx2 = (d.y - c.y), ny2 = (c.x - d.x);

    //两条法线做叉乘, 如果结果为0, 说明线段ab和线段cd平行或共线,不相交  
    var denominator = nx1 * ny2 - ny1 * nx2;
    if (denominator == 0) {
        return null;
    }

    //在法线N2上的投影  
    var distC_N2 = nx2 * c.x + ny2 * c.y;
    var distA_N2 = nx2 * a.x + ny2 * a.y - distC_N2;
    var distB_N2 = nx2 * b.x + ny2 * b.y - distC_N2;

    // 点a投影和点b投影在点c投影同侧 (对点在线段上的情况,本例当作不相交处理);  
    if (distA_N2 * distB_N2 >= 0) {
        return null;
    }

    //  
    //判断点c点d 和线段ab的关系, 原理同上  
    //  
    //在法线N1上的投影  
    var distA_N1 = nx1 * a.x + ny1 * a.y;
    var distC_N1 = nx1 * c.x + ny1 * c.y - distA_N1;
    var distD_N1 = nx1 * d.x + ny1 * d.y - distA_N1;
    if (distC_N1 * distD_N1 >= 0) {
        return null;
    }

    //计算交点坐标  
    var fraction = distA_N2 / denominator;
    var dx = fraction * ny1,
        dy = -fraction * nx1;
    return new PIXI.Point(a.x + dx, a.y + dy);
}
/*
*根据已知点获取第i个控制点的坐标
*   @param ps	已知曲线将经过的坐标点
*   @param i	第i个坐标点
*   @param a,b	可以自定义的正数
*/
// export function getCtrlPoint(ps, i, a, b) {
//     if (!a || !b) {
//         a = 0.25;
//         b = 0.25;
//     }
//     //处理两种极端情形
//     if (ips.length - 3) {
//         var last = ps.length - 1
//         var pBx = ps[last].x - (ps[last].x - ps[last - 1].x) * b;
//         var pBy = ps[last].y - (ps[last].y - ps[last - 1].y) * b;
//     } else {
//         var pBx = ps[i + 1].x - (ps[i + 2].x - ps[i].x) * b;
//         var pBy = ps[i + 1].y - (ps[i + 2].y - ps[i].y) * b;
//     }
//     return {
//         pA: { x: pAx, y: pAy },
//         pB: { x: pBx, y: pBy }
//     }
// }

/**获取点到线的距离 */
export function getPointToLineDis(p: PIXI.Point, line_A: PIXI.Point, line_B: PIXI.Point) {
    var x0 = p.x;
    var y0 = p.y;
    var x1 = line_A.x;
    var y1 = line_A.y;
    var x2 = line_B.x;
    var y2 = line_B.y;
    return Math.abs((y2 - y1) * x0 + (x1 - x2) * y0 + ((x2 * y1) - (x1 * y2))) / Math.sqrt(Math.pow(y2 - y1, 2) + Math.pow(x1 - x2, 2));
}
export function getAnchors(p1x, p1y, p2x, p2y, p3x, p3y) {
    var is_turn = 1;
    if (p3x < p1x) {
        is_turn = -1;
    }
    var l1 = (p2x - p1x) / 2,
        l2 = (p3x - p2x) / 2,
        a = Math.atan((p2x - p1x) / Math.abs(p2y - p1y)),
        b = Math.atan((p3x - p2x) / Math.abs(p2y - p3y));
    a = p1y < p2y ? Math.PI - a : a;
    b = p3y < p2y ? Math.PI - b : b;
    var alpha = Math.PI / 2 - ((a + b) % (Math.PI * 2)) / 2,
        dx1 = l1 * Math.sin(alpha + a),
        dy1 = l1 * Math.cos(alpha + a),
        dx2 = l2 * Math.sin(alpha + b),
        dy2 = l2 * Math.cos(alpha + b);
    return {
        x1: p2x - dx1 * is_turn,
        y1: p2y + dy1 * is_turn,
        x2: p2x + dx2 * is_turn,
        y2: p2y + dy2 * is_turn
    };
}
export function movePointWithDirection(direction: number, move_distance: number, source_point?: Point): Point {
    var xy_rate = Math.tan((direction / 180) * Math.PI);
    var symbol_x = direction < 180 ? 1 : -1;
    var symbol_y = direction > 90 && direction < 270 ? -1 : 1;
    var xy_rate_pow_2 = xy_rate * xy_rate;
    var add_x = symbol_x * move_distance / Math.sqrt(1 + 1 / xy_rate_pow_2);
    var add_y = symbol_y * move_distance / Math.sqrt(1 + xy_rate_pow_2);

    var source_x = source_point ? source_point.x : 0
    var source_y = source_point ? source_point.y : 0
    return {
        x: add_x + source_x,
        y: add_y + source_y,
    }
}